/*
 * $Id: UserService.java 21 2014-09-01 04:28:35Z ratking $
 *
 * Copyleft (C) 2014 RatKing. All wrongs reserved.
 */
package cn.ratking.demo.jaws7.system.service;

import java.util.Collection;
import java.util.Date;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.persistence.EntityManager;

import org.fluttercode.datavalve.DefaultPaginator;
import org.fluttercode.datavalve.Paginator;
import org.fluttercode.datavalve.el.ExpressionParameterResolver;
import org.fluttercode.datavalve.provider.jpa.JpaQueryProvider;
import org.primefaces.model.SortOrder;
import org.slf4j.Logger;

import cn.ratking.demo.jaws7.exception.AppException;
import cn.ratking.demo.jaws7.model.User;
import cn.ratking.demo.jaws7.resource.JawsPU;
import cn.ratking.demo.jaws7.system.vo.UserSearchCriteria;

/**
 * 用户服务
 */
@Stateless
public class UserService {

    @Inject
    private transient Logger log;
    @Inject
    @JawsPU
    private EntityManager em;

    @PostConstruct
    public void init() {
        log.debug("Debug: UserService.init()");
    }

    @PreDestroy
    public void destroy() {
        log.debug("Debug: UserService.destroy()");
    }

    /**
     * 创建用户
     *
     * @param user 用户
     */
    public void create(User user) {
        // 判断用户名是否重复
        String username = user.getUsername();
        User oldUcUser = findByUsername(username);
        if (oldUcUser != null) {
            throw new AppException("用户名[" + username + "]已存在");
        }
        if (user.getCreateTime() == null) {
            // 设置创建时间
            user.setCreateTime(new Date());
        }
        if (user.getUpdateTime() == null) {
            // 设置更新时间
            user.setUpdateTime(user.getCreateTime());
        }
        em.persist(user);
    }

    /**
     * 更新用户
     *
     * @param user 用户
     */
    public void update(User user) {
        // 判断用户名是否重复
        String username = user.getUsername();
        User oldUser = findByUsername(username);
        if (oldUser != null && !oldUser.getUserId().equals(user.getUserId())) {
            throw new AppException("用户名[" + username + "]已存在");
        }
        // 设置更新时间
        user.setUpdateTime(new Date());
        em.merge(user);
    }

    /**
     * 分离实体
     *
     * @param user
     */
    public void detach(User user) {
        em.detach(user);
    }

    /**
     * 按ID删除用户
     *
     * @param userId 用户ID
     */
    public void deleteById(Long userId) {
        // 清除用户与角色关系
        //userRoleService.deleteByUserId(user.getUserId());
        String ql = "DELETE FROM User t"
                + " WHERE t.userId = :userId";
        em.createQuery(ql)
                .setParameter("userId", userId)
                .executeUpdate();
    }

    /**
     * 按ID查询用户
     *
     * @param userId 用户ID
     * @return 用户(找不到时返回null)
     */
    public User findById(Long userId) {
        return em.find(User.class, userId);
    }

    /**
     * 按用户名查询用户
     *
     * @param username 用户名
     * @return 用户(找不到时返回null)
     */
    public User findByUsername(String username) {
        String ql = "SELECT t"
                + " FROM User t"
                + " WHERE t.username = :username";
        List<User> resultList = em.createQuery(ql, User.class)
                .setParameter("username", username)
                .getResultList();
        return resultList.isEmpty() ? null : resultList.get(0);
    }

    /**
     * @todo 应加入角色是否启用的判断
     * @param username
     * @return
     */
    public Collection<String> queryRoles(String username) {
        String ql = "SELECT distinct(t.roleCode)"
                + " FROM UserRole t"
                + " WHERE t.username = :username";
        List<String> resultList = em.createQuery(ql, String.class)
                .setParameter("username", username)
                .getResultList();
        return resultList;
    }

    /**
     *
     * @todo 应加入角色、权限是否启用的判断
     *
     * @param username
     * @return
     */
    public Collection<String> queryPermissions(String username) {
        String ql = "SELECT distinct(rp.permissionCode)"
                + " FROM RolePermisssion rp, UserRole ur"
                + " WHERE rp.roleCode = ur.roleCode"
                + " AND ur.username = :username";
        List<String> resultList = em.createQuery(ql, String.class)
                .setParameter("username", username)
                .getResultList();
        return resultList;
    }

    /**
     * 获得符合查询条件的当前页结果列表
     *
     * @param first 第一条记录(从0开始)
     * @param pageSize 每页记录数
     * @param sortField 排序字段
     * @param sortOrder 排序方向
     * @param filters 过滤条件
     * @param searchCriteria 查询条件
     * @return 结果列表
     */
    public List<User> getResultList(int first, int pageSize,
            String sortField, SortOrder sortOrder,
            UserSearchCriteria searchCriteria) {
        // 查询提供器
        JpaQueryProvider<User> provider = new JpaQueryProvider<User>();
        // 设置实体管理器
        provider.setEntityManager(em);
        // 设置实体类型与别名
        provider.init(User.class, "t");
        // 初始化排序字段映射，可避免恶意SQL注入
        provider.getOrderKeyMap().put("userId", "t.userId");
        provider.getOrderKeyMap().put("username", "t.username");
        provider.getOrderKeyMap().put("realName", "realName");
        provider.getOrderKeyMap().put("sex", "t.sex");
        provider.getOrderKeyMap().put("birthday", "t.birthday");
        provider.getOrderKeyMap().put("enabled", "t.enabled");
        provider.getOrderKeyMap().put("createTime", "t.createTime");
        provider.getOrderKeyMap().put("updateTime", "t.updateTime");
        // 设置表达式参数解析器
        provider.addParameterResolver(new ExpressionParameterResolver());
        // 设置分页与排序
        Paginator paginator = new DefaultPaginator();
        paginator.setFirstResult(first);
        paginator.setMaxRows(pageSize);
        paginator.setOrderKey(sortField);
        paginator.setOrderAscending(sortOrder == SortOrder.ASCENDING);
        // 设置查询约束
        setRestrictions(provider, searchCriteria);
        // 返回查询结果
        return provider.fetchResults(paginator);
    }

    /**
     * 获得符合查询条件的记录总数
     *
     * @param searchCriteria 查询条件
     * @return 记录总数
     */
    public int getRowCount(UserSearchCriteria searchCriteria) {
        // 查询提供器
        JpaQueryProvider<User> provider = new JpaQueryProvider<User>();
        // 设置实体管理器
        provider.setEntityManager(em);
        // 设置实体类型与别名
        provider.init(User.class, "t");
        // 设置表达式参数解析器
        provider.addParameterResolver(new ExpressionParameterResolver());
        // 设置查询约束
        setRestrictions(provider, searchCriteria);
        // 返回查询结果
        int count = provider.fetchResultCount();
        log.debug("Debug: UserService.getRowCount(), count=" + count);
        return count;
    }

    /**
     * 设置查询约束
     *
     * @param queryProvider 查询提供器
     * @param searchCriteria 查询条件
     */
    private void setRestrictions(JpaQueryProvider<User> queryProvider,
            UserSearchCriteria searchCriteria) {
        queryProvider.getRestrictions().clear();

        // 检查调整查询条件中的开始与结束时间
        searchCriteria.checkDate();

        queryProvider.addRestrictionStr("t.username like :param",
                "%" + searchCriteria.getUsername() + "%",
                searchCriteria.getUsername());
        queryProvider.addRestriction("t.createTime >= :param", searchCriteria.getBirthdayBegin());
        queryProvider.addRestriction("t.createTime <= :param", searchCriteria.getBirthdayEnd());
    }
}
